/*
 *    Copyright (C) 2011-2012 Hai Bison
 *
 *    See the file LICENSE at the root directory of this project for copying
 *    permission.
 */

package group.pals.mailgate.media;

import group.pals.threads.BaseThread;
import group.pals.threads.listeners.ThreadAdapter;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Timer;

/**
 *
 * @author Hai Bison
 */
public class SoundPlayer {

    private List<SoundPlayerListener> soundPlayerListeners;
    private OggPlayer oggPlayer;
    private File soundFile;

    private SoundPlayer() {
        this.soundPlayerListeners = new ArrayList<SoundPlayerListener>();
        this.oggPlayer = null;
        this.soundFile = null;
    }

    /**
     * Gets a singleton object of {@link SoundPlayer}.
     * @return {@link SoundPlayer}
     */
    public static SoundPlayer getInstance() {
        return SoundPlayerHolder.INSTANCE;
    }

    /**
     * Although this class is singleton class, but sometime we need to get one instance
     * for testing purpose. This method creates that new one.
     * @return {@link SoundPlayer}
     */
    public static SoundPlayer getNewInstance() {
        return new SoundPlayer();
    }

    /**
     * @return the soundFile
     */
    public File getSoundFile() {
        return soundFile;
    }

    /**
     * @param soundFile the soundFile to set
     */
    public void setSoundFile(File soundFile) {
        this.soundFile = soundFile;
    }

    private static class SoundPlayerHolder {

        private static final SoundPlayer INSTANCE = new SoundPlayer();
    }

    /*----------------------------------------------------------------------------
     * IMPLEMENTATION
     */
    public void addSoundPlayerListener(SoundPlayerListener listener) {
        if (!soundPlayerListeners.contains(listener)) {
            soundPlayerListeners.add(listener);
        }
    }

    public void removeSoundPlayerListener(SoundPlayerListener listener) {
        soundPlayerListeners.remove(listener);
    }

    public void clearAllSoundPlayerListener() {
        soundPlayerListeners.clear();
    }

    public synchronized void play() {
        if (isPlaying()) {
            return;
        }

        try {
            oggPlayer = new OggPlayer(soundFile);
            oggPlayer.addThreadListener(new ThreadAdapter() {

                @Override
                public void threadRaised(BaseThread sender, Exception ex, Object obj) {
                    for (SoundPlayerListener listener : soundPlayerListeners) {
                        listener.soundRaised(SoundPlayer.getInstance(), ex);
                    }
                }

                @Override
                public void threadSuspended(BaseThread sender) {
                    for (SoundPlayerListener listener : soundPlayerListeners) {
                        listener.soundPause(SoundPlayer.getInstance());
                    }
                }

                @Override
                public void threadResumed(BaseThread sender) {
                    for (SoundPlayerListener listener : soundPlayerListeners) {
                        listener.soundPlay(SoundPlayer.getInstance());
                    }
                }

                @Override
                public void threadTerminated(BaseThread sender) {
                    oggPlayer = null;

                    for (SoundPlayerListener listener : soundPlayerListeners) {
                        listener.soundStop(SoundPlayer.getInstance());
                    }
                }
            });
            oggPlayer.start();

            for (SoundPlayerListener listener : soundPlayerListeners) {
                listener.soundPlay(this);
            }
        } catch (Exception ex) {
            //
        }
    }

    public synchronized void stop() {
        if (isPlaying()) {
            oggPlayer.doSuspend();
            Timer timer = new Timer(999, new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    if (oggPlayer != null) {
                        oggPlayer.interrupt();
                    }
                }
            });
            timer.setRepeats(false);
            timer.start();
        }
    }

    public boolean isPlaying() {
        return oggPlayer != null;
    }
}
